/* eslint-disable no-console */
import { logger } from '../types/constants'
import { TimerManager } from './timer_manager'
/**
 * 选择器性能测试用例
 */
export class SelectorPerformanceTest {
  readonly name: string = 'SelectorPerformanceTest'
  private timerManager: TimerManager
  private readonly TEST_ITERATIONS: number = 1000 // 测试迭代次数

  constructor() {
    this.timerManager = TimerManager.getInstance()
  }

  /**
   * 场景1：测试单个ID选择器
   */
  private testSingleIdSelector(): void {
    const stopwatch = this.timerManager.createStopwatch('single-id-test', {
      useHighPrecision: true,
      stopOnLap: false,
    })

    stopwatch.start()

    // 测试原生 querySelector
    for (let i = 0; i < this.TEST_ITERATIONS; i++) {
      const element = document.getElementById('#target-element')
      if (!element)
        throw new Error('元素未找到')
    }

    const nativeTime = stopwatch.getElapsed()
    stopwatch.lapWithNote('原生 querySelector 完成')

    // 测试 jQuery 完整查询
    for (let i = 0; i < this.TEST_ITERATIONS; i++) {
      const element = $('#target-element')[0]
      if (!element)
        throw new Error('元素未找到')
    }

    const jqueryFullTime = stopwatch.getElapsed() - nativeTime
    stopwatch.lapWithNote('jQuery 完整查询 完成')

    // 测试 jQuery find 查询（从容器开始）
    const container = document.getElementById('test-container')
    if (!container)
      throw new Error('容器未找到')

    for (let i = 0; i < this.TEST_ITERATIONS; i++) {
      const element = $(container).find('#target-element')[0]
      if (!element)
        throw new Error('元素未找到')
    }

    const jqueryFindTime = stopwatch.getElapsed() - (nativeTime + jqueryFullTime)
    stopwatch.pause()

    logger.info('🔍 场景1 - 单个ID选择器性能测试结果:', {
      测试迭代次数: this.TEST_ITERATIONS,
      原生querySelector: `${nativeTime.toFixed(3)}ms`,
      jQuery完整查询: `${jqueryFullTime.toFixed(3)}ms`,
      jQueryFind查询: `${jqueryFindTime.toFixed(3)}ms`,
      原生vsjQuery: `原生快 ${((jqueryFullTime - nativeTime) / nativeTime * 100).toFixed(1)}%`,
      Findvs完整查询: `Find快 ${((jqueryFullTime - jqueryFindTime) / jqueryFullTime * 100).toFixed(1)}%`,
    })

    stopwatch.destroy()
  }

  /**
   * 场景2：测试单个Class选择器
   */
  private testSingleClassSelector(): void {
    const stopwatch = this.timerManager.createStopwatch('single-class-test', {
      useHighPrecision: true,
      stopOnLap: false,
    })

    stopwatch.start()

    // 测试原生 querySelector
    for (let i = 0; i < this.TEST_ITERATIONS; i++) {
      const elements = document.querySelectorAll('.level-2')
      if (elements.length === 0)
        throw new Error('元素未找到')
    }

    const nativeTime = stopwatch.getElapsed()
    stopwatch.lapWithNote('原生 querySelectorAll 完成')

    // 测试 jQuery 完整查询
    for (let i = 0; i < this.TEST_ITERATIONS; i++) {
      const elements = $('.level-2')
      if (elements.length === 0)
        throw new Error('元素未找到')
    }

    const jqueryFullTime = stopwatch.getElapsed() - nativeTime
    stopwatch.lapWithNote('jQuery 完整查询 完成')

    // 测试 jQuery find 查询
    const container = document.getElementById('test-container')
    if (!container)
      throw new Error('容器未找到')

    for (let i = 0; i < this.TEST_ITERATIONS; i++) {
      const elements = $(container).find('.level-2')
      if (elements.length === 0)
        throw new Error('元素未找到')
    }

    const jqueryFindTime = stopwatch.getElapsed() - (nativeTime + jqueryFullTime)
    stopwatch.pause()

    logger.info('🔍 场景2 - 单个Class选择器性能测试结果:', {
      测试迭代次数: this.TEST_ITERATIONS,
      原生querySelectorAll: `${nativeTime.toFixed(3)}ms`,
      jQuery完整查询: `${jqueryFullTime.toFixed(3)}ms`,
      jQueryFind查询: `${jqueryFindTime.toFixed(3)}ms`,
      性能对比: this.calculatePerformanceGain(nativeTime, jqueryFullTime, jqueryFindTime),
    })

    stopwatch.destroy()
  }

  /**
   * 场景3：测试ID + Class组合选择器（ID在前）
   */
  private testIdClassSelector(): void {
    const stopwatch = this.timerManager.createStopwatch('id-class-test', {
      useHighPrecision: true,
      stopOnLap: false,
    })

    stopwatch.start()

    // 测试原生 querySelector - #id .class
    for (let i = 0; i < this.TEST_ITERATIONS; i++) {
      const elements = document.querySelectorAll('#test-container .level-2')
      if (elements.length === 0)
        throw new Error('元素未找到')
    }

    const nativeTime = stopwatch.getElapsed()
    stopwatch.lapWithNote('原生 ID+Class 查询完成')

    // 测试 jQuery 完整查询
    for (let i = 0; i < this.TEST_ITERATIONS; i++) {
      const elements = $('#test-container .level-2')
      if (elements.length === 0)
        throw new Error('元素未找到')
    }

    const jqueryFullTime = stopwatch.getElapsed() - nativeTime
    stopwatch.lapWithNote('jQuery ID+Class 查询完成')

    // 测试优化的查询方式 - 先ID后find
    const container = document.getElementById('test-container')
    if (!container)
      throw new Error('容器未找到')

    for (let i = 0; i < this.TEST_ITERATIONS; i++) {
      const elements = $(container).find('.level-2')
      if (elements.length === 0)
        throw new Error('元素未找到')
    }

    const jqueryFindTime = stopwatch.getElapsed() - (nativeTime + jqueryFullTime)
    stopwatch.pause()

    logger.info('🔍 场景3 - ID+Class组合选择器性能测试结果:', {
      测试迭代次数: this.TEST_ITERATIONS,
      选择器模式: '#id .class',
      原生查询: `${nativeTime.toFixed(3)}ms`,
      jQuery完整查询: `${jqueryFullTime.toFixed(3)}ms`,
      jQuery优化查询: `${jqueryFindTime.toFixed(3)}ms`,
      优化效果: this.calculateOptimizationGain(jqueryFullTime, jqueryFindTime),
    })

    stopwatch.destroy()
  }

  /**
   * 场景4：测试Class + Class组合选择器
   */
  private testClassClassSelector(): void {
    const stopwatch = this.timerManager.createStopwatch('class-class-test', {
      useHighPrecision: true,
      stopOnLap: false,
    })

    stopwatch.start()

    // 测试原生 querySelector - .class .class
    for (let i = 0; i < this.TEST_ITERATIONS; i++) {
      const elements = document.querySelectorAll('.level-1 .level-2')
      if (elements.length === 0)
        throw new Error('元素未找到')
    }

    const nativeTime = stopwatch.getElapsed()
    stopwatch.lapWithNote('原生 Class+Class 查询完成')

    // 测试 jQuery 完整查询
    for (let i = 0; i < this.TEST_ITERATIONS; i++) {
      const elements = $('.level-1 .level-2')
      if (elements.length === 0)
        throw new Error('元素未找到')
    }

    const jqueryFullTime = stopwatch.getElapsed() - nativeTime
    stopwatch.lapWithNote('jQuery Class+Class 查询完成')

    // 测试优化的查询方式 - 先缩小范围
    const containers = document.querySelectorAll('.level-1')
    if (containers.length === 0)
      throw new Error('容器未找到')

    for (let i = 0; i < this.TEST_ITERATIONS; i++) {
      let totalElements = 0
      containers.forEach((container) => {
        const elements = $(container).find('.level-2')
        totalElements += elements.length
      })
      if (totalElements === 0)
        throw new Error('元素未找到')
    }

    const jqueryFindTime = stopwatch.getElapsed() - (nativeTime + jqueryFullTime)
    stopwatch.pause()

    logger.info('🔍 场景4 - Class+Class组合选择器性能测试结果:', {
      测试迭代次数: this.TEST_ITERATIONS,
      选择器模式: '.class .class',
      原生查询: `${nativeTime.toFixed(3)}ms`,
      jQuery完整查询: `${jqueryFullTime.toFixed(3)}ms`,
      jQuery优化查询: `${jqueryFindTime.toFixed(3)}ms`,
      性能分析: this.analyzeClassSelectorPerformance(nativeTime, jqueryFullTime, jqueryFindTime),
    })

    stopwatch.destroy()
  }

  /**
   * 计算性能提升百分比
   */
  private calculatePerformanceGain(nativeTime: number, jqueryFullTime: number, jqueryFindTime: number): string {
    const nativeVsJQuery = ((jqueryFullTime - nativeTime) / nativeTime * 100).toFixed(1)
    const findVsFull = ((jqueryFullTime - jqueryFindTime) / jqueryFullTime * 100).toFixed(1)

    return `原生快${nativeVsJQuery}% | Find比完整查询快${findVsFull}%`
  }

  /**
   * 计算优化效果
   */
  private calculateOptimizationGain(fullTime: number, findTime: number): string {
    const gain = ((fullTime - findTime) / fullTime * 100).toFixed(1)
    return findTime < fullTime ? `优化后快${gain}%` : `优化后慢${Math.abs(Number(gain))}%`
  }

  /**
   * 分析Class选择器性能
   */
  private analyzeClassSelectorPerformance(nativeTime: number, jqueryFullTime: number, jqueryFindTime: number): any {
    return {
      原生性能比: `原生是jQuery的${(jqueryFullTime / nativeTime).toFixed(2)}倍`,
      优化效果: `优化查询比完整查询快${((jqueryFullTime - jqueryFindTime) / jqueryFullTime * 100).toFixed(1)}%`,
      推荐方案: jqueryFindTime < jqueryFullTime ? '使用find优化' : '直接使用完整查询',
    }
  }

  /**
   * 运行完整的性能测试套件
   */
  async runCompleteTestSuite(): Promise<void> {
    logger.info('🚀 开始元素选择器性能测试套件', 'SelectorPerformanceTest')

    try {
      // 预热（避免第一次执行较慢）
      await this.warmUp()

      // 执行各个场景测试
      this.testSingleIdSelector()
      await this.delay(100) // 间隔避免相互影响

      this.testSingleClassSelector()
      await this.delay(100)

      this.testIdClassSelector()
      await this.delay(100)

      this.testClassClassSelector()

      // 生成总结报告
      this.generateSummaryReport()
    }
    catch (error) {
      logger.error('性能测试执行失败:', error)
    }
    finally {
      logger.info('✅ 元素选择器性能测试完成', 'SelectorPerformanceTest')
    }
  }

  /**
   * 预热函数（避免第一次执行较慢）
   */
  private async warmUp(): Promise<void> {
    logger.debug('🔥 预热测试环境...', 'SelectorPerformanceTest')

    // 执行一些简单的查询来预热
    for (let i = 0; i < 10; i++) {
      document.querySelector('#target-element')
      $('.level-1')
    }

    await this.delay(50)
  }

  /**
   * 延迟函数
   */
  private delay(ms: number): Promise<void> {
    return new Promise(resolve => setTimeout(resolve, ms))
  }

  /**
   * 生成总结报告
   */
  private generateSummaryReport(): void {
    const state = this.timerManager.getState()

    logger.info('📊 选择器性能测试总结报告', 'PerformanceReport')
    console.log(`
┌─────────────────────────────────────────────────────────────┐
│                元素选择器性能测试报告                     │
├─────────────────────────────────────────────────────────────┤
│ 📊 测试场景数量: 4 种选择器模式                           │
│ 🔄 每种测试迭代次数: ${this.TEST_ITERATIONS} 次                  │
│ ⚡ 使用高精度计时器: 是                                  │
│ 📈 活动计时器数量: ${state.stopwatches.length}                  │
│ 🎯 测试目标: 对比原生/jQuery/优化查询性能                │
└─────────────────────────────────────────────────────────────┘

💡 性能优化建议:
• 单个ID选择器: 优先使用原生 document.getElementById()
• 复杂选择器: 考虑使用 querySelector + 缓存结果
• jQuery使用: 对于已知容器，使用 $(container).find() 优于全局查询
• Class选择器: 尽量避免深层嵌套的类选择器

🔧 最佳实践:
1. ID查询 → document.getElementById() 最快
2. 简单选择器 → 原生 querySelector 足够
3. 复杂查询 → 先缩小范围再使用 find()
4. 频繁操作 → 缓存选择器结果
    `)
  }
}

/**
 * 使用示例和测试运行函数
 */
export async function runSelectorPerformanceTest(): Promise<void> {
  const test = new SelectorPerformanceTest()

  // 设置测试参数（可选）
  // test.testIterations = 5000 // 增加测试次数提高准确性

  await test.runCompleteTestSuite()
}

// 直接运行测试（如果是在浏览器环境中）
if (typeof window !== 'undefined' && window.jQuery) {
  // 页面加载完成后自动运行测试
  document.addEventListener('DOMContentLoaded', () => {
    setTimeout(() => {
      runSelectorPerformanceTest().catch(console.error)
    }, 1000)
  })
}
